/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <conio.h>
#include <QFile>
#include <QMessageBox>
#include <shlwapi.h>
#include <QDir>
#include "iphlpapi.h"
#include "LibMain.h"
#include "BurnToolCommon/Global.h"
#include "../platform/Securec/securec.h"
#include "util.h"

using namespace UtilClass;
using namespace LibMainClass;
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cpluscplus */
#endif /* __cpluscplus */

void MutMsTimer(unsigned long ulMsInterval)
{
    LARGE_INTEGER stPerfFrequency;
    LARGE_INTEGER stStartCount;
    LARGE_INTEGER stEndCount;
    if (ulMsInterval == 0) {
        return;
    }
    QueryPerformanceFrequency(&stPerfFrequency);
    QueryPerformanceCounter(&stStartCount);
    for (;;) {
        if (ulMsInterval >= SHORT_INTV) {
            Sleep(1);
        }
        QueryPerformanceCounter(&stEndCount);
        if (stPerfFrequency.QuadPart == 0) {
            continue;
        }
        if (((stEndCount.QuadPart - stStartCount.QuadPart)
            * 1000 / stPerfFrequency.QuadPart) >= ulMsInterval) { // 1000 time between ms and μs
            break;
        }
    }
    return;
}

unsigned long MutGetFileLen(FILE* pFile)
{
    unsigned long ulFileLen;
    fseek(pFile, 0, SEEK_END);
    ulFileLen = ftell(pFile);
    fseek(pFile, 0, SEEK_SET);
    return ulFileLen;
}

unsigned long MutGetImgFileCRC(FILE* pFile)
{
    long lFileLen;
    char* pszFileBuff;
    long lReadLen;

    if (pFile == nullptr) {
        return TSP_D_ERR_MUT_PARAMETER_ERR;
    }
    lFileLen = MutGetFileLen(pFile);
    if (lFileLen <= 0) {
        return TSP_D_ERR_MUT_INTERNAL_ERR;
    }
    pszFileBuff = (char*)malloc((lFileLen + 1) * sizeof(char));
    if (pszFileBuff == nullptr) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    fseek(pFile, 0, SEEK_SET);
    lReadLen = fread(pszFileBuff, sizeof(char), lFileLen, pFile);
    if (lReadLen == lFileLen) {
        LibMain::ulImgFileCRC = MutCrcCompute(reinterpret_cast<unsigned char*>(pszFileBuff), lFileLen);
        free(pszFileBuff);
        if (LibMain::ulImgFileCRC != 0) {
            return MUT_OK;
        }
        return MUT_OK;
    } else {
        free(pszFileBuff);
        return TSP_D_ERR_MUT_INTERNAL_ERR;
    }
}

unsigned long MutGetFileSegment(FILE* pFilePtr, unsigned long ulPosition, char* pszBuff, unsigned long ulBuffSize)
{
    unsigned long ulReadLen;
    FILE* pTmp = pFilePtr;
    if (pszBuff == nullptr || ulBuffSize == 0) {
        return TSP_D_ERR_MUT_PARAMETER_ERR;
    }
    if (MutGetFileLen(pTmp) <= ulPosition) {
        return TSP_D_ERR_MUT_INTERNAL_ERR;
    }
    fseek(pTmp, ulPosition, SEEK_SET);
    ulReadLen = fread(pszBuff, sizeof(char), ulBuffSize, pTmp);
    return ulReadLen;
}

unsigned long TspMutGetConfigInfo()
{
    strcpy_s(LibMain::pszMulticastIp, sizeof(LibMain::pszMulticastIp), DEFAULT_MULTICAST_IP);
    strcpy_s(LibMain::pszIntervalTime, sizeof(LibMain::pszIntervalTime), DEFAULT_INTERVAL_TIME);
    return MUT_OK;
}

unsigned long MutCrcCmp(char* pszBuffer, unsigned long ulBufLen, unsigned long ulCRC)
{
    if (ulCRC == MutCrcCompute(reinterpret_cast<unsigned char*>(pszBuffer), ulBufLen)) {
        return MUT_OK;
    } else {
        return TSP_D_ERR_MUT_CRC_CMP_NOK;
    }
}

unsigned long TspMutGetIniFileName(const char* pszPath)
{
    if (pszPath == nullptr) {
        return TSP_D_ERR_MUT_PARAMETER_ERR;
    }
    int ret = memset_s(LibMain::pszIniFileName, MAX_FILE_PATH + 1, 0, MAX_FILE_PATH + 1);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    char* pszTmp = strchr((pszPath + strlen(pszPath) - FILE_NAME_EXTENSION_LEN), POINT_CHARACTER);
    if (pszTmp) {
        ret = strncpy_s(LibMain::pszIniFileName, MAX_FILE_PATH + 1,
        pszPath, strlen(pszPath) - FILE_NAME_EXTENSION_LEN);
    } else {
        ret = strncpy_s(LibMain::pszIniFileName, MAX_FILE_PATH + 1, pszPath, strlen(pszPath));
    }
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    ret = strncat_s(LibMain::pszIniFileName, MAX_FILE_PATH + 1, INI_POSTFIX, INI_POSTFIX_LEN);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    return MUT_OK;
}

unsigned long MutParseIniFile(const char* pszIniFileName)
{
    QFile file;
    fpos_t pos;
    unsigned long ulTmp;
    unsigned long ulRet;
    unsigned long ulCRC;
    unsigned long ulIniBuffLen = 0;
    
    if (pszIniFileName == nullptr) {
        return TSP_D_ERR_MUT_PARAMETER_ERR;
    }
    char pszImgNameValue[MAX_ITEM_LEN + 1] = {0};
    char pszImgSizeValue[MAX_ITEM_LEN + 1] = {0};
    char pszFirmVerValue[MAX_ITEM_LEN + 1] = {0};
    char pszPCBVerValue[MAX_ITEM_LEN + 1] = {0};
    char pszFirmCRCValue[MAX_ITEM_LEN + 1] = {0};
    char pszIniCRCValue[MAX_ITEM_LEN + 1] = {0};
    char pszIniFileBuff[MAX_INI_FILE_LEN + 1] = {0};
    pszImgNameValue[0] = '\0';
    pszImgSizeValue[0] = '\0';
    pszFirmVerValue[0] = '\0';
    pszPCBVerValue[0]  = '\0';
    pszFirmCRCValue[0] = '\0';
    pszIniCRCValue[0]  = '\0';
    int ret = memset_s(pszIniFileBuff, MAX_INI_FILE_LEN + 1, 0, MAX_INI_FILE_LEN + 1);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    ret = memset_s(LibMain::pszPkgIDValue, MAX_PKG_ID_LEN + 1, 0, MAX_PKG_ID_LEN + 1);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    ret = memset_s(LibMain::pszProductIDValue, MAX_PRODUCT_ID_LEN + 1, 0, MAX_PRODUCT_ID_LEN + 1);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    QString cleanPath = QDir::cleanPath(pszIniFileName);
    if (cleanPath.isEmpty()) {
        return TSP_D_ERR_MUT_PARAMETER_ERR;
    }
    FILE* pFile = fopen(cleanPath.toUtf8(), "rb"); // read方式打开
    if (pFile == nullptr) {
        QMessageBox::warning(nullptr, "error", "Make sure the file exists and is readable.");
        return TSP_D_ERR_MUT_OPEN_FILE_ERR;
    }
    for (;;) {
        ulTmp = MutReadOneLine(pFile);
        if (ulTmp == TSP_D_ERR_MUT_EOF) {
            break;
        } else if (ulTmp != MUT_OK) {
            fclose(pFile);
            return ulTmp;
        }
        if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_IMG_NAME)) {
            ret = strncpy_s(pszImgNameValue, MAX_ITEM_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_IMG_NAME) + 1, MAX_ITEM_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_IMG_SIZE)) {
            ret = strncpy_s(pszImgSizeValue, MAX_ITEM_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_IMG_SIZE) + 1, MAX_ITEM_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_PKG_ID)) {
            ret = strncpy_s(LibMain::pszPkgIDValue, MAX_PKG_ID_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_PKG_ID) + 1, MAX_PKG_ID_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_PRDCT_ID)) {
            ret = strncpy_s(LibMain::pszProductIDValue, MAX_PRODUCT_ID_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_PRDCT_ID) + 1, MAX_PRODUCT_ID_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_FIRMWARE_VER)) {
            ret = strncpy_s(pszFirmVerValue, MAX_ITEM_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_FIRMWARE_VER) + 1, MAX_ITEM_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_PCB_VER)) {
            ret = strncpy_s(pszPCBVerValue, MAX_ITEM_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_PCB_VER) + 1, MAX_ITEM_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_FIRMWARE_CRC)) {
            ret = strncpy_s(pszFirmCRCValue, MAX_ITEM_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_FIRMWARE_CRC) + 1, MAX_ITEM_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
            fgetpos(pFile, &pos);
            if (fseek(pFile, INI_FILE_BUFFER_OFFSET, SEEK_CUR) == 0) {
                ulIniBuffLen = ftell(pFile);
                fseek(pFile, 0, SEEK_SET);
                fread(pszIniFileBuff, sizeof(char), ulIniBuffLen, pFile);
                fsetpos(pFile, &pos);
                continue;
            } else {
                fclose(pFile);
                return TSP_D_ERR_MUT_FILE_STRUCT_ERR;
            }
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_INI_CRC)) {
            ret = strncpy_s(pszIniCRCValue, MAX_ITEM_LEN + 1,
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_INI_CRC) + 1, MAX_ITEM_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
            continue;
        } else if (strstr(LibMain::pszFileOneLineBuff, INI_ITEM_PARTITIONS)) {
            char patition[1025] = { 0 };
            ret = strncpy_s(patition, sizeof(patition),
                LibMain::pszFileOneLineBuff + strlen(INI_ITEM_PARTITIONS) + 1, PATITION_LEN);
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
            QString patitionStr = QString::fromUtf8(patition, sizeof(patition));
            QStringList patitionList = patitionStr.split("|");
            for (int i = 0; i < patitionList.size(); i++) {
                QStringList patitionListInfo = patitionList[i].split(",");
                if (patitionListInfo.size() != PATITION_PARAMETER_NUM) {
                    continue;
                }
                if (memcpy_s(LibMain::stPatitions[i].partitionName, sizeof(LibMain::stPatitions[i].partitionName),
                             patitionListInfo[0].toUtf8().data(),
                             patitionListInfo[0].toUtf8().size()) != 0) {
                    continue;
                }
                QStringList patitionListAddr = patitionListInfo[1].split("-");
                if (patitionListAddr.size() != ADDR_PARAMETER_NUM) {
                    continue;
                }
                bool ok = false;
                LibMain::stPatitions[i].addrStart = patitionListAddr[0].toULong(&ok, 0x10);
                LibMain::stPatitions[i].addrEnd = patitionListAddr[1].toULong(&ok, 0x10);
                LibMain::stPatitions[i].cover = ((patitionListInfo[PATITION_COVER_INDEX] == "cover")
                    ? PATITION_CHECK : PATITION_NOT_CHECK);
            }
            continue;
        } else if (strncmp(LibMain::pszFileOneLineBuff, "//", sizeof("//")) == 0 ||
                   strncmp(LibMain::pszFileOneLineBuff, "*", sizeof("*")) == 0) {
            continue;
        }
    }
    if (((pszImgNameValue[0] == '\0' || pszImgSizeValue[0] == '\0' ||
        pszFirmVerValue[0] == '\0' || pszPCBVerValue[0]  == '\0' ||
        pszFirmCRCValue[0] == '\0' || pszIniCRCValue[0]  == '\0' ||
        LibMain::pszPkgIDValue[0]   == '\0' || LibMain::pszProductIDValue[0] == '\0')) ||
        (strchr(pszImgNameValue, '=') != nullptr ||
         strchr(pszImgSizeValue, '=') != nullptr ||
         strchr(pszFirmVerValue, '=') != nullptr ||
         strchr(pszPCBVerValue, '=') != nullptr ||
         strchr(pszFirmCRCValue, '=') != nullptr ||
         strchr(pszIniCRCValue, '=') != nullptr ||
         strchr(LibMain::pszPkgIDValue, '=') != nullptr ||
         strchr(LibMain::pszProductIDValue, '=') != nullptr)) {
        fclose(pFile);
        return TSP_D_ERR_MUT_FILE_STRUCT_ERR;
    }
    fclose(pFile);
    ulCRC = strtoul(pszIniCRCValue, nullptr, DECIMAL_NUM);
    if (ulIniBuffLen == 0) {
        return TSP_D_ERR_MUT_FILE_STRUCT_ERR;
    }
    ulRet = MutCrcCmp(pszIniFileBuff, ulIniBuffLen, ulCRC);
    return ulRet;
}

unsigned long MutReadOneLine(FILE* pFile)
{
    if (pFile == nullptr) {
        return TSP_D_ERR_MUT_PARAMETER_ERR;
    }
    if (fgets(LibMain::pszFileOneLineBuff, MAX_FILE_ONE_LINE_LEN, pFile)) {
        // 去掉每行最后的回车符
        int returnCharLen = sizeof("\r\n");
        if (strncmp((LibMain::pszFileOneLineBuff + strlen(LibMain::pszFileOneLineBuff) - returnCharLen),
            "\r\n", returnCharLen) == 0) {
            int ret = memset_s((LibMain::pszFileOneLineBuff + strlen(LibMain::pszFileOneLineBuff) - returnCharLen),
                returnCharLen, 0, returnCharLen);
            if (ret != 0) {
                return TSP_D_ERR_MUT_EOF;
            }
        }
        int newLineCharLen = sizeof("\n");
        if (strncmp((LibMain::pszFileOneLineBuff + strlen(LibMain::pszFileOneLineBuff) - newLineCharLen),
            "\n", newLineCharLen) == 0) {
            int ret = memset_s((LibMain::pszFileOneLineBuff + strlen(LibMain::pszFileOneLineBuff) - newLineCharLen),
                newLineCharLen, 0, newLineCharLen);
            if (ret != 0) {
                return TSP_D_ERR_MUT_EOF;
            }
        }
        return MUT_OK;
    } else {
        if (feof(pFile) != 0) {
            return TSP_D_ERR_MUT_EOF;
        } else {
            return TSP_D_ERR_MUT_FILE_STRUCT_ERR;
        }
    }
}

unsigned long BuildPacket(unsigned long ulTmp, long lCRC)
{
    int ret = memcpy_s(LibMain::pszPacketBuff, ONE_PACKET_BUFF_LEN, &ulTmp,
        LEN_OF_PACKET_TYPE_AND_LEN); // 报文类型号和报文长度
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_SEQUENCE_NUMBER_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_SEQUENCE_NUMBER_OFFSET, &LibMain::ulPacketNo,
            PACKET_SEQUENCE_NUMBER_LEN); // 报文顺序号
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    if (lCRC > 0) {
        ret = memcpy_s(LibMain::pszPacketBuff + PACKET_CRC_OFFSET,
            ONE_PACKET_BUFF_LEN - PACKET_CRC_OFFSET, &lCRC, PACKET_CRC_LEN); // CRC校验和
        if (ret != 0) {
            return TSP_D_ERR_MUT_EOF;
        }
    }
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_IMG_LEN_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_IMG_LEN_OFFSET, &LibMain::ulImgFileLen, PACKET_IMG_LEN_LEN); // 映像文件总长
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_IMG_CRC_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_IMG_CRC_OFFSET, &LibMain::ulImgFileCRC, PACKET_IMG_CRC_LEN); // 映像文件CRC值
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_ID_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_ID_OFFSET, LibMain::pszPkgIDValue, PACKET_ID_LEN); // 包特征字符串
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_PRODUCT_ID_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_PRODUCT_ID_OFFSET, LibMain::pszProductIDValue, PACKET_PRODUCT_ID_LEN); // 软件标识
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    return MUT_OK;
}

unsigned long MutBuildPacket(const char* pszSegBuff, unsigned long ulPacketLen)
{
    int ret = memset_s(LibMain::pszPacketBuff, ONE_PACKET_BUFF_LEN, 0, ONE_PACKET_BUFF_LEN);
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    unsigned long ulPackLen = (ulPacketLen >= ONE_SEGMENT_BUFF_LEN) ? ONE_SEGMENT_BUFF_LEN : ulPacketLen;
    long lCRC = MutCrcCompute(reinterpret_cast<const unsigned char*>(pszSegBuff), ulPackLen); // CRC校验
    unsigned long ulTmp = ONE_SEGMENT_BUFF_LEN | (0x20 << 24); // 24 indicates the left shift by 24 bits

    ret = BuildPacket(ulTmp, lCRC);
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_SEG_BUFFER_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_SEG_BUFFER_OFFSET, pszSegBuff, ulPackLen);
    if (ret != 0) {
        return TSP_D_ERR_MUT_EOF;
    }
    return MUT_OK;
}

unsigned long MutBuildPartitionPacket(unsigned long ulPacketLen)
{
    long lCRC = 0;
    unsigned long ulPackLen = 0;
    unsigned long ulTmp = 0;
    int ret = memset_s(LibMain::pszPacketBuff, ONE_PACKET_BUFF_LEN, 0, ONE_PACKET_BUFF_LEN);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    ulPackLen = (ulPacketLen >= ONE_SEGMENT_BUFF_LEN) ? ONE_SEGMENT_BUFF_LEN : ulPacketLen;
    unsigned long ulTmp2 = ONE_SEGMENT_BUFF_LEN;
    ulTmp = ulTmp2 | (0x80 << 24); // 24 indicates the left shift by 24 bits
    ret = BuildPacket(ulTmp, lCRC);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    for (int i = 0; i < PATITION_NUM_MAX; i++) {
        if (LibMain::stPatitions[i].partitionName[0] != 0) {
            ret = memcpy_s(LibMain::pszPacketBuff + PACKET_SEG_BUFFER_OFFSET + i * sizeof(LibMain::PATITION),
                           ONE_PACKET_BUFF_LEN - (PACKET_SEG_BUFFER_OFFSET + i * sizeof(LibMain::PATITION)),
                           &LibMain::stPatitions[i], sizeof(LibMain::PATITION));
            if (ret != 0) {
                return TSP_D_ERR_MUT_MALLOC_ERR;
            }
        }
    }
    lCRC = MutCrcCompute(reinterpret_cast<unsigned char*>(LibMain::pszPacketBuff)
        + PACKET_SEG_BUFFER_OFFSET, ulPackLen); // CRC校验
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_CRC_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_CRC_OFFSET, &lCRC, PACKET_CRC_LEN); // CRC校验和
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    return MUT_OK;
}

unsigned long MutBuildEndPacket(unsigned long ulPacketLen)
{
    long lCRC = 0;
    unsigned long ulPackLen = 0;
    unsigned long ulTmp = 0;
    int ret = memset_s(LibMain::pszPacketBuff, ONE_PACKET_BUFF_LEN, 0, ONE_PACKET_BUFF_LEN);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    ulPackLen = (ulPacketLen >= ONE_SEGMENT_BUFF_LEN) ? ONE_SEGMENT_BUFF_LEN : ulPacketLen;
    unsigned long ulTmp2 = ONE_SEGMENT_BUFF_LEN;
    ulTmp = ulTmp2 | (0x40 << 24); // 24 indicates the left shift by 24 bits
    ret = BuildPacket(ulTmp, lCRC);
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    lCRC = MutCrcCompute(reinterpret_cast<unsigned char*>(LibMain::pszPacketBuff)
        + PACKET_SEG_BUFFER_OFFSET, ulPackLen); // CRC校验
    ret = memcpy_s(LibMain::pszPacketBuff + PACKET_CRC_OFFSET,
        ONE_PACKET_BUFF_LEN - PACKET_CRC_OFFSET, &lCRC, PACKET_CRC_LEN); // CRC校验和
    if (ret != 0) {
        return TSP_D_ERR_MUT_MALLOC_ERR;
    }
    return MUT_OK;
}

unsigned long MutCrcCompute(const unsigned char* csData, unsigned long len)
{
    unsigned long crcPoly = 0xEDB88320;  // Inversion bit sequence of 0x04C11DB7
    unsigned long data = 0xFFFFFFFF; // initial value

    for (unsigned long i = 0; i < len; i++) {
        data ^= csData[i];
        for (int j = 8; j > 0; --j) {
            data = (((data >> 1) ^ (data & 1)) != 0) ? crcPoly : 0;
        }
    }
    return data ^ 0xFFFFFFFF;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cpluscplus */
#endif /* __cpluscplus */
